/**
* Project: yui3-common-mybatisx
 * Class InjectorMapperRegistry
 * Version 1.0
 * File Created at 2019年1月21日
 * $Id$
 * author yuyi
 * email 1060771195@qq.com
 */
package yui.comn.mybatisx.core;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.binding.BindingException;
import org.apache.ibatis.binding.MapperRegistry;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;

import com.baomidou.mybatisplus.core.override.MybatisMapperProxyFactory;

/**
 * <p>
 * 注解解析注册类
 * 通过注解的方式注入基础CRUD方法,和一对一, 一对多连表方法
 * <p>
 * @author yuyi (1060771195@qq.com)
 */
public class InjectorMapperRegistry extends MapperRegistry {

    private final Configuration config;
    private final Map<Class<?>, MybatisMapperProxyFactory<?>> knownMappers = new HashMap<>();

    public InjectorMapperRegistry(Configuration config) {
        super(config);
        this.config = config;
    }
    
    
    @SuppressWarnings("unchecked")
    @Override
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        // TODO 这里换成 MybatisMapperProxyFactory 而不是 MapperProxyFactory
        final MybatisMapperProxyFactory<T> mapperProxyFactory = (MybatisMapperProxyFactory<T>) knownMappers.get(type);
        if (mapperProxyFactory == null) {
            throw new BindingException("Type " + type + " is not known to the MybatisPlusMapperRegistry.");
        }
        try {
            return mapperProxyFactory.newInstance(sqlSession);
        } catch (Exception e) {
            throw new BindingException("Error getting mapper instance. Cause: " + e, e);
        }
    }

    public <T> boolean hasMapper(Class<T> type) {
        return knownMappers.containsKey(type);
    }
    
    public <T> void addMapper(Class<T> type) {
        if (type.isInterface()) {
            if (hasMapper(type)) {
                // TODO 如果之前注入 直接返回
                return;
                // throw new BindingException("Type " + type +
                // " is already known to the MybatisMapperRegistry.");
            }
            boolean loadCompleted = false;
            try {
                knownMappers.put(type, new MybatisMapperProxyFactory<>(type));
                
                InjectorMapperAnnotationBuilder builder = new InjectorMapperAnnotationBuilder(config, type);
                builder.parse();
                
                loadCompleted = true;
            } finally {
                if (!loadCompleted) {
                    knownMappers.remove(type);
                }
            }
        }
    }
    
    /**
     * 使用自己的 knownMappers
     */
    @Override
    public Collection<Class<?>> getMappers() {
        return Collections.unmodifiableCollection(knownMappers.keySet());
    }
}
